﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Yz.Base.Base;
using Yz.Base.Config;
using Yz.Base.Constants;
using Yz.Base.Enums;
using Yz.Core.Extensions;
using Yz.Core.Tools;

namespace Yz.Web.Controllers
{
    public class UeditorController : BaseController
    {
        private readonly UeditorConfig _ueditorConfig;
        private readonly IWebHostEnvironment _webHostEnv;
        public UeditorController(
            IOptions<UeditorConfig> ueditorConfigOption,
            IWebHostEnvironment webHostEnv)
        {
            _ueditorConfig = ueditorConfigOption.Value;
            _webHostEnv = webHostEnv;
        }
        /// <summary>
        /// 对接ueditor的文件上传
        /// </summary>
        /// <returns></returns> 
        [HttpPost]
        public async Task<JsonResult> Upload()
        {
            string action = Request.Query.Where(p => p.Key == "action").Select(p => p.Value).FirstOrDefault();
            JsonResult json = null;
            switch (action.ToLower())
            {
                case UeditorUploadConstant.Config:
                    Response.Headers.Add("Content-Type", "text/plain");
                    json = Json(_ueditorConfig);
                    break;
                case UeditorUploadConstant.UploadImage:
                    json = await UploadFile(new UeditorUploadConfig
                    {
                        AllowExtensions = _ueditorConfig.ImageAllowFiles,
                        PathFormat = _ueditorConfig.ImagePathFormat,
                        SizeLimit = _ueditorConfig.ImageMaxSize,
                        UploadFieldName = _ueditorConfig.ImageFieldName
                    });
                    break;
                case UeditorUploadConstant.UploadScrawl:
                    json = await UploadFile(new UeditorUploadConfig
                    {
                        AllowExtensions = new List<string>() { ".png" },
                        PathFormat = _ueditorConfig.ScrawlPathFormat,
                        SizeLimit = _ueditorConfig.ScrawlMaxSize,
                        UploadFieldName = _ueditorConfig.ScrawlFieldName,
                        Base64 = true,
                        Base64Filename = "scrawl.png"
                    });
                    break;
                case UeditorUploadConstant.UploadVideo:
                    json = await UploadFile(new UeditorUploadConfig
                    {
                        AllowExtensions = _ueditorConfig.VideoAllowFiles,
                        PathFormat = _ueditorConfig.VideoPathFormat,
                        SizeLimit = _ueditorConfig.VideoMaxSize,
                        UploadFieldName = _ueditorConfig.VideoFieldName
                    });
                    break;
                case UeditorUploadConstant.UploadFile:
                    json = await UploadFile(new UeditorUploadConfig
                    {
                        AllowExtensions = _ueditorConfig.FileAllowFiles,
                        PathFormat = _ueditorConfig.FilePathFormat,
                        SizeLimit = _ueditorConfig.FileMaxSize,
                        UploadFieldName = _ueditorConfig.FileFieldName
                    });
                    break;
                //case UeditorUploadConstant.ListImage:
                //    action = new ListFileManager(context, Config.GetString("imageManagerListPath"), Config.GetStringList("imageManagerAllowFiles"));
                //    break;
                //case UeditorUploadConstant.ListFile:
                //    action = new ListFileManager(context, Config.GetString("fileManagerListPath"), Config.GetStringList("fileManagerAllowFiles"));
                //    break;
                //case UeditorUploadConstant.CatchImage:
                //    action = new CrawlerHandler(context);
                //    break;
                default:
                    json = Json(new
                    {
                        state = "action 参数为空或者 action 不被支持。"
                    });
                    break;
            }
            return json;
        }

        public JsonResult GetConfig()
        {
            Response.Headers.Add("Content-Type", "text/plain");
            return Json(_ueditorConfig);
        }
        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="uploadConfig"></param>
        /// <returns></returns>
        //[HttpPost]
        //[Route("ueditor/uploadfile/{action}")]
        private async Task<JsonResult> UploadFile(UeditorUploadConfig uploadConfig)
        {
            UeditorUploadResult result = new UeditorUploadResult()
            {
                State = GetStateMessage(UeditorUploadState.Unknown)
            };
            byte[] uploadFileBytes = null;
            string uploadFileName = null;

            if (uploadConfig.Base64)
            {
                uploadFileName = uploadConfig.Base64Filename;
                uploadFileBytes = Convert.FromBase64String(Request.Query.Where(p => p.Key == uploadConfig.UploadFieldName).Select(p => p.Value).FirstOrDefault());
            }
            else
            {
                var file = Request.Form.Files[uploadConfig.UploadFieldName];
                uploadFileName = file.FileName;

                if (!CheckFileType(uploadConfig, uploadFileName))
                {
                    result.State = GetStateMessage(UeditorUploadState.TypeNotAllow);
                    return Json(result);
                }
                if (!CheckFileSize(uploadConfig, file.Length))
                {
                    result.State = GetStateMessage(UeditorUploadState.SizeLimitExceed);
                    return Json(result);
                }

                uploadFileBytes = new byte[file.Length];
                try
                {
                    file.OpenReadStream().Read(uploadFileBytes, 0, file.Length.ToInt());
                }
                catch (Exception ex)
                {
                    YzNLog.Error(ex);
                    result.State = GetStateMessage(UeditorUploadState.NetworkError);
                }
            }

            result.Original = uploadFileName;
            var flExtension = result.Original.Substring(result.Original.LastIndexOf('.')).ToLower();

            string fileRootPath = FileRootPath;
            var localPath = _webHostEnv.WebRootPath + fileRootPath;
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", fileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);


            try
            {
                using (var fileStream = new FileStream(fileLocalPath, FileMode.Create, FileAccess.Write))
                {
                    await fileStream.WriteAsync(uploadFileBytes, 0, uploadFileBytes.Length);
                    fileStream.Flush(true);
                }
                result.Url = filePath;
                result.State = GetStateMessage(UeditorUploadState.Success);
            }
            catch (Exception e)
            {
                result.State = GetStateMessage(UeditorUploadState.FileAccessError);
                result.Error = e.Message;
            }
            return Json(result);

        }
        private string GetStateMessage(UeditorUploadState state)
        {
            switch (state)
            {
                case UeditorUploadState.Success:
                    return "SUCCESS";
                case UeditorUploadState.FileAccessError:
                    return "文件访问出错，请检查写入权限";
                case UeditorUploadState.SizeLimitExceed:
                    return "文件大小超出服务器限制";
                case UeditorUploadState.TypeNotAllow:
                    return "不允许的文件格式";
                case UeditorUploadState.NetworkError:
                    return "网络错误";
            }
            return "未知错误";
        }
        private bool CheckFileType(UeditorUploadConfig uploadConfig, string filename)
        {
            var fileExtension = Path.GetExtension(filename).ToLower();
            return uploadConfig.AllowExtensions.Select(x => x.ToLower()).Contains(fileExtension);
        }

        private bool CheckFileSize(UeditorUploadConfig uploadConfig, long size)
        {
            return size < uploadConfig.SizeLimit;
        }
    }
}
